#pragma once

#ifdef __linux__

#include "knx/platform.h"
#include <string>

extern int gpio_direction(int pin, int dir);
extern int gpio_read(int pin);
extern int gpio_write(int pin, int value);
extern int gpio_export(int pin);
extern int gpio_unexport(int pin);

class LinuxPlatform : public Platform {
public:
  LinuxPlatform();
  virtual ~LinuxPlatform();

  void cmdLineArgs(int argc, char **argv);

  std::string flashFilePath();
  void flashFilePath(const std::string path);

  // basic stuff
  void restart() override;
  void fatalError() override;

  // ip config
  uint32_t currentIpAddress() override;
  uint32_t currentSubnetMask() override;
  uint32_t currentDefaultGateway() override;
  void macAddress(uint8_t *data) override;

  // multicast
  void setupMultiCast(uint32_t addr, uint16_t port) override;
  void closeMultiCast() override;
  bool sendBytesMultiCast(uint8_t *buffer, uint16_t len) override;
  int readBytesMultiCast(uint8_t *buffer, uint16_t maxLen) override;
  bool sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t *buffer,
                        uint16_t len) override;

  // UART
  void setupUart() override;
  void closeUart() override;
  int uartAvailable() override;
  size_t writeUart(const uint8_t data) override;
  size_t writeUart(const uint8_t *buffer, size_t size) override;
  int readUart() override;
  size_t readBytesUart(uint8_t *buffer, size_t length) override;

  // spi
  void setupSpi() override;
  void closeSpi() override;
  int readWriteSpi(uint8_t *data, size_t len) override;

  // memory
  uint8_t *getEepromBuffer(uint32_t size) override;
  void commitToEeprom() override;
  void cmdlineArgs(int argc, char **argv);

private:
  uint32_t _multicastAddr = -1;
  uint16_t _multicastPort = -1;
  int _multicastSocketFd = -1;

  void doMemoryMapping();
  uint8_t *_mappedFile = 0;
  int _fd = -1;
  int _spiFd = -1;
  int _uartFd = -1;
  std::string _flashFilePath = "flash.bin";
  char **_args = 0;

  uint8_t _macAddress[6] = {0, 0, 0, 0, 0, 0};
  uint32_t _ipAddress = 0;
  uint32_t _netmask = 0;
  uint32_t _defaultGateway = 0;
};

#endif
